﻿/// <reference path="../../../../Resources/Shared/scripts/jquery/jquery.js" />
/// <reference path="../../../../Resources/Shared/scripts/knockout.js" />


/*|============================================
    | webApiExplorer
    |     This is a global object acting as my
    | application's "namespace".
    |============================================*/
function WebApiExplorer($, ko) {
    var self = this;
    function ScriptBuilder() {
        // NOTE: Indenting of body of scriptNamespace() intentional (for rendering in <pre> tags)
        // NOTE: Do NOT attempt to run this function - it's only there to "hold" a template
        function scriptNamespaceTemplate() {
// A) Place this in a script block in your .ascx code - (See Footnote A)
$(function () {
    // TODO: Find a better name than "obj"
    // Pass JQuery and KnockoutJS to your constructor
    var obj = new $ServiceRootScript($, ko);
    obj.init($ModuleId, $ModuleClientId);
});

// B) Place this in a JavaScript file in your module (See Footnote B)
function $ServiceRootScript($, ko) {
    // 1) Capture this, for namespacing purposes.
    var self = this;

    // 2) If you're using KnockoutJs, you could set the ViewModel here
    self.data = {
        // Setup ko.observable and ko.observableArray items:
        info: ko.observable()
    };

    self.init = function init(moduleId, elementId) {
        // 3) Instantiating the Services Framework for your module
        self.sf = $.ServicesFramework(moduleId);

        // 4) Scripting the Ajax call
        $.ajax({
            type: $AjaxType,
            url: self.sf.getServiceRoot($ServiceRootName)
                    + $Controller_ShortName / $Method_Name,
            beforeSend: self.sf.setModuleHeaders,
            data: $Method_ParameterArgument
        }).done(function (serverData, textStatus) {
            if (textStatus === "success") {
                // Process your data from the server. E.g.:
                self.data.info(serverData);
                ko.applyBindings(self.data, document.getElementById($(elementId).attr("id")));
            } else {
                // Give appropriate feedback to the user; e.g.:
                displayMessage('#' + elementId, // placeholderSelector - such as '#$ModuleNameDiv'
                                "Your error message here", // Server responded, but not with a success status
                                "dnnFormWarning");
            }
        }).fail(function (xhr, status) {
            // Give appropriate feedback to the user; e.g.:
            displayMessage('#' + elementId, // placeholderSelector - such as '#$ModuleNameDiv'
                            "Your error message here", // server did not process request (service was not found)
                            "dnnFormWarning");
        });
    };

    /* Utilities:
        *  displayMessage - as taken from DotNetNuke: CoreMessaging.js, lines 17-27
        */
    function displayMessage(placeholderSelector, message, cssclass) {
        var messageNode = $("<div/>")
                .addClass('dnnFormMessage ' + cssclass)
                .text(message);

        $(placeholderSelector).prepend(messageNode);

        messageNode.fadeOut(3000, 'easeInExpo', function () {
            messageNode.remove();
        });
    };


    /* --------------
    * Notes:
    *  A) Note the inline code for a .ascx to get the ModuleID and the client-side .ascx ID
    *      obj.init($ModuleId, '$ModuleClientId');
    *  B) The following items are specific to your script:
    *      $ServiceRootScript => A namespace you could use for your JavaScript.
    *      $ServiceRootName => The name that you set up as the route name
    *          (first parameter in your call to MapHttpRoute(); 
    *           see your IServiceRouteMapper instance's RegsiterRoutes() method)
    *      $Controller_ShortName => The name of your controller class
    *          (without the "Controller" part that appends your class name;
    *           it should also inherit from DnnApiController)
    *      $Method_Name => The name of the method on your controller class
    *      $ModuleNameDiv => A possible unique ID for an element on your module
    */
};
        };

        // Placeholder Constants:
        var $apiCode = "<span class='apiCode'>'CODE'</span>";
        var $code = "CODE";
        var $ModuleId = "<%= ModuleId %>";
        var $ModuleClientId = "'<%=apiExplorerModule.ClientID %>'";
        var $AjaxType_Get = $apiCode.replace($code, "GET");
        var $AjaxType_Post = $apiCode.replace($code, "POST");
        var $AjaxType_Put = $apiCode.replace($code, "PUT");
        var $AjaxType_Delete = $apiCode.replace($code, "DELETE");
        var $ModuleNameDiv = "#ModuleName_ModuleID";

        // Placeholder Variables
        var $ServiceRootScript,
            $ServiceRootName,
            $AjaxType,
            $Controller_ShortName,
            $Method_Name,
            $Method_ParameterArgument;


        function getFnBody(func, subStr, newSubStr) {
            return func.toString().replace(subStr, newSubStr).substring(func.toString().indexOf("{") + 1, func.toString().lastIndexOf("}"));
        };

        return function (serviceRoot, controllerShortName, methodName, methodParamStructure, httpAttributes) {
            // Init Placeholder Variables
            $ServiceRootScript = serviceRoot + 'Script';
            $ServiceRootName = $apiCode.replace($code, serviceRoot);
            $Controller_ShortName = $apiCode.replace($code, controllerShortName);
            $Method_Name = $apiCode.replace($code, methodName);
            $Method_ParameterArgument = methodParamStructure;

            for (var index in httpAttributes) {
                switch (httpAttributes[index].ShortName) {
                    case 'HttpGet':
                        $AjaxType = $AjaxType_Get;
                        break;
                    case 'HttpPost':
                        $AjaxType = $AjaxType_Post;
                        break;
                    case 'HttpPut':
                        $AjaxType = $AjaxType_Put;
                        break;
                    case 'HttpDelete':
                        $AjaxType = $AjaxType_Delete;
                        break;
                    default:
                        break;
                }
            }

            var codeBlock = getFnBody(scriptNamespaceTemplate);
            codeBlock = codeBlock.replaceAll('$ModuleId', $ModuleId);
            codeBlock = codeBlock.replaceAll('$ModuleClientId', $ModuleClientId);
            codeBlock = codeBlock.replaceAll('$ModuleNameDiv', $ModuleNameDiv);
            codeBlock = codeBlock.replaceAll('$ServiceRootScript', $ServiceRootScript);
            codeBlock = codeBlock.replaceAll('$ServiceRootName', $ServiceRootName);
            codeBlock = codeBlock.replaceAll('$AjaxType', $AjaxType);
            codeBlock = codeBlock.replaceAll('$Controller_ShortName', $Controller_ShortName);
            codeBlock = codeBlock.replaceAll('$Method_Name', $Method_Name);
            codeBlock = codeBlock.replaceAll('$Method_ParameterArgument', $Method_ParameterArgument);

            return codeBlock;
        }
    };
    var scriptBuilder = new ScriptBuilder();

    self.data = {
        routes: ko.observableArray(),
        selectedRoute: ko.observable(),
        selectedCode: ko.observable(),
        noDetails: function (controllers) {
            var show = controllers.length === 0;
            return show;
        },
        exploreDetails: function (route) {
            self.data.selectedRoute(route.RouteName);
        },
        exploreCode: function (methodData, methodDataParents) {
            return function () {
                self.data.selectedCode(methodDataParents[1].ServiceRoot + '_' + methodDataParents[0].ShortName + '_' + methodData.Name);
            }
        },
        showDetails: function (route) {
            return route === self.data.selectedRoute();
        },
        showCode: function (methodData, methodDataParents) {
            return self.data.selectedCode() === methodDataParents[1].ServiceRoot + '_' + methodDataParents[0].ShortName + '_' + methodData.Name;
        },
        closeDetails: function () { self.data.selectedRoute(''); },
        closeCode: function () { self.data.selectedCode(''); },
        buildScript: function (methodData, methodDataParents) {
            var serviceRoot = methodDataParents[1].ServiceRoot;
            var controllerShortName = methodDataParents[0].ShortName;
            var methodName = methodData.Name;
            var methodParamStructure = null;
            var httpAttributes = methodData.Attributes;
            var script = scriptBuilder(serviceRoot, controllerShortName, methodName, methodParamStructure, httpAttributes);
            // console.log(script);
            return script;
        },
        buildCodeId: function (methodData, methodDataParents) {
            return methodDataParents[1].ServiceRoot + '_' + methodDataParents[0].ShortName + '_' + methodData.Name;
        }
    };

    self.init = function init(ascxModuleId, elementId) {
        self.sf = $.ServicesFramework(ascxModuleId);

        $.ajax({
            type: "GET",
            url: self.sf.getServiceRoot('WebApiExplorerService') + 'WebApi/GetRichRouteData',
            beforeSend: self.sf.setModuleHeaders
        }).done(function (data, textStatus) {
            if (textStatus === "success") {
                self.data.routes(data);
                ko.applyBindings(self.data, document.getElementById($(elementId).attr("id")));
            } else {
                // Give appropriate feedback to the user; e.g.:
                displayMessage('#' + elementId,
                               "The WebApi request returned the following status: " + textStatus,
                               "dnnFormWarning");
            }
        }).fail(function (xhr, result, status) {
            displayMessage(elementId,
                           "The WebApi request failed: " + status,
                           "dnnFormWarning");
        });
    };

    var containerElement = null;
    function displayMessage(placeholderSelector, message, cssclass) {
        var messageNode = $("<div/>")
                .addClass('dnnFormMessage ' + cssclass)
                .text(message);

        $(placeholderSelector).prepend(messageNode);

        messageNode.fadeOut(3000, 'easeInExpo', function () {
            messageNode.remove();
        });
    };
};
